package com.husj.dynamicdao;

import com.husj.dynamicdao.exceptions.DynamicDaoException;
import com.husj.dynamicdao.proxy.DynamicDaoProxyFactory;
import com.husj.dynamicdao.support.DynamicDaoConfiguration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.sql.DataSource;

/**
 * 无spring环境使用该方式获取动态dao代理
 *
 * @author shengjun.hu
 * @date 2021/6/23
 */
public class DynamicDaoTemplate {

    private DataSource dataSource;
    private JdbcTemplate jdbcTemplate;
    private DynamicDaoConfiguration configuration;
    private PlatformTransactionManager transactionManager;
    private final ThreadLocal<TransactionStatus> transactionStatusThreadLocal = new ThreadLocal<>();

    public DynamicDaoTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
        this.configuration = DynamicDaoConfiguration.builder().build();
        this.jdbcTemplate = new JdbcTemplate(this.dataSource);
        this.transactionManager = new DataSourceTransactionManager(this.dataSource);
    }

    public DynamicDaoTemplate(DataSource dataSource, DynamicDaoConfiguration configuration) {
        this.dataSource = dataSource;
        this.configuration = configuration;
        this.jdbcTemplate = new JdbcTemplate(this.dataSource);
        this.transactionManager = new DataSourceTransactionManager(this.dataSource);
    }

    /**
     * 开启事务
     */
    public void begin() {
        TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
        transactionStatusThreadLocal.set(transactionStatus);
    }

    /**
     * 提交事务
     */
    public void commit() {
        TransactionStatus transactionStatus = transactionStatusThreadLocal.get();
        if (transactionStatus == null) {
            throw new DynamicDaoException("提交事务失败！");
        }
        transactionStatusThreadLocal.remove();
        transactionManager.commit(transactionStatus);
    }

    /**
     * 回滚事务
     */
    public void rollback() {
        TransactionStatus transactionStatus = transactionStatusThreadLocal.get();
        if (transactionStatus == null) {
            throw new DynamicDaoException("回滚事务失败！");
        }
        transactionStatusThreadLocal.remove();
        transactionManager.rollback(transactionStatus);
    }

    /**
     * 获取dao的代理
     * @param interfaceType
     * @param <T>
     * @return
     */
    public <T> T getDynamicDao(Class<T> interfaceType) {
        return DynamicDaoProxyFactory.create(interfaceType, jdbcTemplate, configuration);
    }

}
